package cloud.keveri.response4j.aop;

import cloud.keveri.base.KeveriException;
import cloud.keveri.base.result.Response;
import cloud.keveri.response4j.ResponseMaker;
import cloud.keveri.response4j.SkipWrap;
import cloud.keveri.response4j.StringResponseWrapper;
import cloud.keveri.response4j.skip.SkipWrapCheckFunction;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

import static cloud.keveri.response4j.Response4jErrorCodeConstants.NOT_HANDLER;

/**
 * <p>
 * 作者：沈自在
 **/
@ControllerAdvice
@Order(value = 1000)
public class DefaultGlobalResponseAdvice implements ResponseBodyAdvice<Object> {

    private final ResponseMaker responseMaker;

    private final List<SkipWrapCheckFunction> skipWrapCheckFunctions;

    public DefaultGlobalResponseAdvice(ResponseMaker responseMaker,
                                       List<SkipWrapCheckFunction> skipWrapCheckFunctions) {
        this.responseMaker = responseMaker;
        this.skipWrapCheckFunctions = skipWrapCheckFunctions;
    }

    @Override
    public boolean supports(@NonNull MethodParameter methodParameter,
                            @NonNull Class<? extends HttpMessageConverter<?>> converterType) {
        // 1. 解析方法
        Method method = methodParameter.getMethod();

        // 2. 处理特殊情况
        if (Objects.isNull(method) ||
                !MappingJackson2HttpMessageConverter.class.isAssignableFrom(converterType)) {
            return false;
        }

        // 3. 注解跳过
        if (method.isAnnotationPresent(SkipWrap.class)) {
            return false;
        }

        // 4. 补充逻辑
        for (SkipWrapCheckFunction func : skipWrapCheckFunctions) {
            boolean isSkip = func.isSkip(methodParameter, converterType);
            if (isSkip) {
                return false;
            }
        }

        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body,
                                  @NonNull MethodParameter methodParameter,
                                  @NonNull MediaType selectedContentType,
                                  @NonNull Class<? extends HttpMessageConverter<?>> converterType,
                                  @NonNull ServerHttpRequest request,
                                  @NonNull ServerHttpResponse response) {
        // 1. 处理 Void
        Method method = methodParameter.getMethod();
        assert method != null;
        if (method.getReturnType().equals(Void.TYPE)) {
            return responseMaker.newSuccessInstance();
        }

        // 2. 处理有返回值
        if (body == null) {
            return responseMaker.newSuccessInstance();
        } else if (body instanceof Response) {
            return body;
        } else {
            return responseMaker.newSuccessInstance(body);
        }
    }
}
